//
//  StatisticsCache.swift
//  hello
//
//  Created by 赵康 on 2025/3/31.
//

import Redis
import Foundation

struct StatisticsCache {
	private let cache: Cache
	private let redis: RedisClient
	private let logger: Logger
	init(cache: Cache, redis: RedisClient) {
		self.cache = cache
		self.redis = redis
		self.logger = cache.logger
	}
	
		// 1. 获取每日统计数据
	func getDailyStatistics(
		userID: UUID,
		date: Date,
		tagID: UUID?
	) async throws -> Double? {
		let dayStart = Calendar.mondayFirst.startOfDay(for: date)
		let key = CacheConfig.KeyBuilder.dailyStatistics(
			userID: userID,
			date: dayStart,
			tagID: tagID
		)
		
		let result = try await cache.get(
			forKey: key,
			as: Double.self,
			from: redis
		)
		return result
	}
	
		// 2. 设置每日统计数据
	func setDailyStatistics(
		userID: UUID,
		date: Date,
		tagID: UUID?,
		duration: Double
	) async throws {
		let dayStart = Calendar.mondayFirst.startOfDay(for: date)
		let key = CacheConfig.KeyBuilder.dailyStatistics(
			userID: userID,
			date: dayStart,
			tagID: tagID
		)
		
		try await cache.set(
			duration,
			forKey: key,
			duration: CacheConfig.Duration.Statistics.daily,
			type: .statistics,
			on: redis
		)
	}
	
		// 3. 获取月度统计数据
	func getMonthlyStatistics(
		userID: UUID,
		date: Date,
		tagID: UUID?
	) async throws -> Double? {
		let monthStart = Calendar.mondayFirst.startOfMonth(for: date)
		let key = CacheConfig.KeyBuilder.monthlyStatistics(
			userID: userID,
			month: monthStart,
			tagID: tagID
		)
		
		return try await cache.get(
			forKey: key,
			as: Double.self,
			from: redis
		)
	}
	
		// 4. 设置月度统计数据
	func setMonthlyStatistics(
		userID: UUID,
		date: Date,
		tagID: UUID?,
		duration: Double
	) async throws {
		let monthStart = Calendar.mondayFirst.startOfMonth(for: date)
		let key = CacheConfig.KeyBuilder.monthlyStatistics(
			userID: userID,
			month: monthStart,
			tagID: tagID
		)
		try await cache.set(
			duration,
			forKey: key,
			duration: CacheConfig.Duration.Statistics.monthly,
			type: .statistics,
			on: redis
		)
	}
		// 获取年统计数据
	func getYearlyStatistics(
		userID: UUID,
		tagID: UUID?
	) async throws -> Double? {
		let key = CacheConfig.KeyBuilder.yearlyStatistics(
			userID: userID,
			tagID: tagID
		)
		return try await cache.get(
			forKey: key,
			as: Double.self,
			from: redis
		)
	}
	func setYearlyStatistics(
		userID: UUID,
		tagID: UUID?,
		duration: Double
	) async throws {
		let key = CacheConfig.KeyBuilder.yearlyStatistics(
			userID: userID,
			tagID: tagID
		)
		try await cache.set(
			duration,
			forKey: key,
			duration: CacheConfig.Duration.veryLong,
			type: .statistics,
			on: redis
		)
	}
		// 获取排行榜数据
	func getRanking(
		timeRange: TimeRange,
		tagID: UUID?
	) async throws -> [StatisticsService.RankingResponse]? {
		let key = CacheConfig.KeyBuilder.userRanking(
			timeRange: timeRange,
			tagID: tagID
		)
		return try await cache.get(
			forKey: key,
			as: [StatisticsService.RankingResponse].self,
			from: redis
		)
	}
	
		// 设置排行榜数据
	func setRanking(
		timeRange: TimeRange,
		tagID: UUID?,
		rankings: [StatisticsService.RankingResponse]
	) async throws {
		let key = CacheConfig.KeyBuilder.userRanking(
			timeRange: timeRange,
			tagID: tagID
		)
    
		try await cache.set(
			rankings,
			forKey: key,
			duration: CacheConfig.Duration.medium,
			type: .statistics,
			on: redis
			
		)
	}
	func invalidateStatistics(
		userID: UUID,
		date: Date,
		tagID: UUID?
	) async throws {
			// 失效日统计缓存
		let dailyKey = CacheConfig.KeyBuilder.dailyStatistics(
			userID: userID,
			date: date,
			tagID: tagID
		)
		try await cache.delete(forKey: dailyKey, on: redis)
		logger.debug("已失效日统计缓存 - Key: \(dailyKey)")
		
			// 同时失效月度缓存
		let monthlyKey = CacheConfig.KeyBuilder.monthlyStatistics(
			userID: userID,
			month: date,
			tagID: tagID
		)
		try await cache.delete(forKey: monthlyKey, on: redis)
		logger.debug("已失效月度统计缓存 - Key: \(monthlyKey)")
	}
	func clearRangeStatistics(
		userID: UUID,
		startDate: Date,
		endDate: Date,
		tagID: UUID?
	) async throws {
		var currentDate = Calendar.mondayFirst.startOfDay(for: startDate)
		let rangeEnd = Calendar.mondayFirst.startOfDay(for: endDate)
		
		while currentDate <= rangeEnd {
			try await invalidateStatistics(
				userID: userID,
				date: currentDate,
				tagID: tagID
			)
			currentDate = Calendar.mondayFirst.date(byAdding: .day, value: 1, to: currentDate)!
		}
		
		logger.debug("已清理 \(startDate) 至 \(endDate) 的统计缓存")
	}
	
	// 删除指定的缓存键
	func delete(forKey key: RedisKey, on redis: RedisClient) async throws {
		try await cache.delete(forKey: key, on: redis)
		logger.debug("已删除缓存 - Key: \(key)")
	}
}


extension StatisticsCache {
	// 获取用户最近7天的音频数量缓存
	func getRecentAudiosCount(userID: UUID) async throws -> Int? {
		let key = CacheConfig.KeyBuilder.recentAudiosCount(userID: userID)
		return try await cache.get(forKey: key, as: Int.self, from: redis)
	}
	
	// 设置用户最近7天的音频数量缓存
	func setRecentAudiosCount(userID: UUID, count: Int) async throws {
		let key = CacheConfig.KeyBuilder.recentAudiosCount(userID: userID)
		try await cache.set(
			count,
			forKey: key,
			duration: CacheConfig.Duration.medium,
			type: .statistics,
			on: redis
		)
	}
	
	// 获取所有用户最近7天的音频数量分布缓存
	func getAllUsersRecentAudiosDistribution() async throws -> [Int]? {
		let key = CacheConfig.KeyBuilder.allUsersRecentAudiosDistribution()
		return try await cache.get(forKey: key, as: [Int].self, from: redis)
	}
	
	// 设置所有用户最近7天的音频数量分布缓存
	func setAllUsersRecentAudiosDistribution(distribution: [Int]) async throws {
		let key = CacheConfig.KeyBuilder.allUsersRecentAudiosDistribution()
		try await cache.set(
			distribution,
			forKey: key,
			duration: CacheConfig.Duration.medium,
			type: .statistics,
			on: redis
		)
	}
	
	// 获取用户标签分布的缓存
	func getTagsDistribution(userID: UUID) async throws -> TagDistributionResponse? {
		let key = CacheConfig.KeyBuilder.tagsDistribution(userID: userID)
		return try await cache.get(
			forKey: key,
			as: TagDistributionResponse.self,
			from: redis
		)
	}
	
	// 设置用户标签分布的缓存
	func setTagsDistribution(userID: UUID, distribution: TagDistributionResponse) async throws {
		let key = CacheConfig.KeyBuilder.tagsDistribution(userID: userID)
		try await cache.set(
			distribution,
			forKey: key,
			duration: CacheConfig.Duration.medium,
			type: .statistics,
			on: redis
		)
	}
}
